﻿namespace OpenComposite.Repository.Forms.TrackingMonitor
{
	using System;
	using System.Collections.Generic;
	using System.ComponentModel;
	using System.Data;
	using System.Drawing;
	using System.Globalization;
	using System.Linq;
	using System.Text;
	using System.Windows.Forms;

	using OpenComposite.Base;
	using OpenComposite.Repository.Properties;

	using WeifenLuo.WinFormsUI.Docking;
	using System.Workflow.Runtime.Tracking;
	using OpenComposite.Workflow.Interfaces;
	using System.Workflow.ComponentModel;
	using OpenComposite.Repository.Tracking;

	public partial class TrackedActivityDetails : DockContent
	{
		#region Initialization

		public TrackedActivityDetails()
		{
			InitializeComponent();
		}

		#endregion Initialization

		#region Internal Members

		#region Events

		internal event EventHandler<EventArgs<TrackedProcessInstance>> LoadAssembly;

		#endregion Events

		#region Methods

		internal void LoadDetails(TrackedProcessInstance process, TrackedActivityInstance activity)
		{
			bool changedActivity = false;

			if ( activity != null ) {
				changedActivity = true;
				gbxProcessInfo.Visible = false;
				gbxActivityInfo.Visible = true;
				this.TopLevelControl.Refresh();
				txtActName.Text = activity.Name;
				txtActStatus.Text = activity.Status.ToString();
				txtActTime.Text = activity.Time.ToString(CultureInfo.CurrentUICulture.DateTimeFormat.FullDateTimePattern);
				txtActType.Text = activity.Instance.ActivityType == null ? "(unknown)" : activity.Instance.ActivityType.FullName;
				_currentActivity = activity;
			}

			if ( process != null ) {
				gbxProcessInfo.Visible = true;
				gbxActivityInfo.Visible = false;
				this.TopLevelControl.Refresh();
				txtWfInstanceId.Text = process.Instance.WorkflowInstanceId.ToString();
				txtWfStatus.Text = process.Status.ToString();
				txtWfInitialized.Text = process.Instance.Initialized.ToString(CultureInfo.CurrentUICulture.DateTimeFormat.FullDateTimePattern);
				txtWfAssembly.Text = process.Instance.WorkflowAssemblyName;
				txtWfWorkflowType.Text = process.Instance.WorkflowTypeName;
				_currentProcess = process;
				this.TopLevelControl.Refresh();
				updateAssemblyStatus();
			}
			this.TopLevelControl.Refresh();

			gbxExceptionData.Visible = false;
			if ( _currentProcess != null ) {
				foreach ( WorkflowTrackingRecord record in _currentProcess.Instance.WorkflowEvents ) {
					TrackingWorkflowExceptionEventArgs args = record.EventArgs as TrackingWorkflowExceptionEventArgs;
					if ( args != null && args != EventArgs.Empty ) {
						if ( changedActivity && args.CurrentActivityPath != activity.Name ) continue;
						gbxExceptionData.Visible = true;
						txtExceptionType.Text = args.Exception.GetType().Name;
						txtExceptionMessage.Text = args.Exception.Message;
						try { // try here to catch rare assembly resolve errors at WorkflowDefinition. (if Assembly is not available at tracking time)
							Activity act = _currentProcess.Instance.WorkflowDefinition.GetActivityByName(args.OriginalActivityPath);
							if ( act != null && act is ITextActivity ) {
								txtExceptionSourceActivity.Text = string.Format("{0} ({1})", ( (ITextActivity)act ).Text, act.QualifiedName);
							} else {
								txtExceptionSourceActivity.Text = args.OriginalActivityPath;
							}
						} catch {
							txtExceptionSourceActivity.Text = args == null ? "(unknown)" : args.OriginalActivityPath;
						}
						break;
					}
				}
			}
		}

		#endregion Methods

		#endregion Internal Members

		#region Private Members

		#region Fields

		TrackedActivityInstance _currentActivity;
		TrackedProcessInstance _currentProcess;

		#endregion Fields

		#region Event Handlers

		private void btnLoadAsembly_Click(object sender, EventArgs e)
		{
			updateAssemblyStatus();
			EventHandler<EventArgs<TrackedProcessInstance>> tmp = LoadAssembly;
			if ( tmp != null ) {
				LoadAssembly(this, new EventArgs<TrackedProcessInstance>(_currentProcess));
			}
		}

		#endregion Event Handlers

		#region Methods

		private void updateAssemblyStatus()
		{
			Type type = null;
			try {
				type = Type.GetType(_currentProcess.Instance.WorkflowFullTypeName, false);
			} finally {
				picAssemblyStatus.Image = type == null ? Resources.png_cancel : Resources.png_ok;
			}
		}

		#endregion Methods

		#endregion Private Members
	}
}